package net.jgrm.idgenerator.service.impl;

import lombok.extern.slf4j.Slf4j;
import net.jgrm.idgenerator.service.IdGenerator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.PostConstruct;
import java.util.concurrent.TimeUnit;

/**
 * 基于Redis自增的ID生成器实现
 */
@Slf4j
//@Component
//@ConditionalOnExpression("'${id.generator.type}'.equalsIgnoreCase('redis')")
public class RedisIdGenerator implements IdGenerator {

    private RedisTemplate<String, Object> redisTemplate;

    public RedisIdGenerator(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    // Redis键前缀
    @Value("${id.generator.redis.key-prefix:id:generator}")
    private String keyPrefix;

    // 默认自增步长
    @Value("${id.generator.redis.step:1}")
    private long defaultStep;

    // key过期时间（秒），默认7天
    @Value("${id.generator.redis.expire:604800}")
    private long expireSeconds;

    @PostConstruct
    public void init() {
        log.info("Redis ID生成器初始化成功");
    }

    @Override
    public Long nextId() {
        return nextId("default");
    }

    @Override
    public Long nextId(String businessType) {
        return nextId(businessType, defaultStep);
    }

    @Override
    public Long[] batchNextId(int count) {
        Long[] ids = new Long[count];
        for (int i = 0; i < count; i++) {
            ids[i] = nextId();
        }
        return ids;
    }

    /**
     * 生成指定业务类型和步长的唯一ID
     *
     * @param businessType 业务类型
     * @param step         自增步长
     * @return 唯一ID
     */
    public Long nextId(String businessType, long step) {
        if (businessType == null || businessType.trim().isEmpty()) {
            businessType = "default";
        }
        String redisKey = buildRedisKey(businessType);
        try {
            // 使用Redis的INCRBY命令自增
            Long id = redisTemplate.opsForValue().increment(redisKey, step);
            if (expireSeconds > 0) {
                redisTemplate.expire(redisKey, expireSeconds, TimeUnit.SECONDS);
            }
            // 设置过期时间（如果是新创建的key）
//            if (id != null && id.equals(step)) {
//                log.info("Redis ID生成器：创建新的ID序列，业务类型: {}, Redis键: {}, 过期时间: {}秒",
//                        businessType, redisKey, expireSeconds);
//            }

            log.info("Redis ID生成器：生成ID成功，业务类型: {}, ID: {}", businessType, id);
            return id;
        } catch (Exception e) {
            log.error("Redis ID生成器：生成ID失败，业务类型: {}", businessType, e);
            throw new RuntimeException("Redis ID生成器：生成ID失败", e);
        }
    }

    /**
     * 构建Redis键
     */
    private String buildRedisKey(String businessType) {
        return String.format("%s:%s", keyPrefix, businessType);
    }

    /**
     * 重置指定业务类型的ID序列
     *
     * @param businessType 业务类型
     * @return 是否重置成功
     */
    public boolean reset(String businessType) {
        try {
            String redisKey = buildRedisKey(businessType);
            redisTemplate.delete(redisKey);
            log.info("Redis ID生成器：重置ID序列成功，业务类型: {}", businessType);
            return true;
        } catch (Exception e) {
            log.error("Redis ID生成器：重置ID序列失败，业务类型: {}", businessType, e);
            return false;
        }
    }

    /**
     * 获取指定业务类型的当前ID值
     *
     * @param businessType 业务类型
     * @return 当前ID值，如果不存在则返回null
     */
    public Long getCurrentId(String businessType) {
        try {
            String redisKey = buildRedisKey(businessType);
            Object value = redisTemplate.opsForValue().get(redisKey);
            return value != null ? Long.valueOf(value.toString()) : null;
        } catch (Exception e) {
            log.error("Redis ID生成器：获取当前ID值失败，业务类型: {}", businessType, e);
            return null;
        }
    }
}